<template>
    <div>
        <div class="cameraUpload">
            <div>
                <el-button @click="photograph">拍照</el-button>
                <!-- 默认摄像头是打开的 即 跳转到这个页面的时候摄像头是打开的 -->
                <el-button v-if="flag" @click="openCamera">打开摄像头</el-button>
                <el-button v-else @click="closeCamera">关闭摄像头</el-button>
                <el-button @click="resetForm">重置</el-button>
                <el-button @click="submitGostudentInfo">提交</el-button>
            </div>
            <!-- 把宽高设为动态属性是因为很多地方都用到了这个值 -->
            <video id="videoCamera" class="videoCamera" :width="videoWidth" :height="videoHeight">

            </video>
            <canvas id="canvasCamera" class="canvasCamera" :width="videoWidth" :height="videoHeight">

            </canvas>

        </div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            flag: false,
            videoWidth: 350,
            videoHeight: 250,
            thisVideo: null,//使用该属性  获取到video元素
            thisCanvas: null,//画布初始值
            thisContext: null,//画笔初始值
            imgSrc: ''//照片的初始值
        }
    },

    methods: {
        //打开本地摄像头
        openCamera() {
            //切换flag的状态，使打开摄像头 变为 关闭摄像头
            this.flag = false;
            //获取到video
            this.thisVideo = document.getElementById("videoCamera");

            // 想要打开本地摄像头，就要用到navigator.mediaDevices.getUserMedia，但是有的浏览器没有，这里就要做兼容性处理

            // 兼容性处理
            //第一层 旧版本浏览器 不支持mediaDevices  我们就将navigator.mediaDevices设置成一个空对象。
            if (navigator.mediaDevices === undefined) {
                navigator.mediaDevices = {};
            }
            //第二层 有的浏览器有navigator.mediaDevices，但是没有getUserMedia ，或者会覆盖该属性，我们则要处理
            if (navigator.mediaDevices.getUserMedia === undefined) {
                //即 当getUserMedia不存在的时候，我们去创一个
                // constraints 传入音频视频文件信息
                navigator.mediaDevices.getUserMedia = function (constraints) {
                    //获取 不同浏览器内核 的getUserMedia
                    let getUserMedia =
                        navigator.webkitGetUserMedia ||
                        navigator.mozGetUserMedia ||
                        navigator.getUserMedia;

                    //如果在这些浏览器内核之外的浏览器，也就是还没有getUserMedia，就告诉用户 更换浏览器
                    if (!getUserMedia) {
                        return Promise.reject(new Error("请更换浏览器"));
                    }

                    //如果有了getUserMedia （在不同内核中有） 将其给navigator
                    return new Promise((resolve, reject) => {
                        getUserMedia.call(navigator, constraints, resolve, reject);
                    });
                }
            }
            //constraints 传入音、视频文件信息
            const constraints = {
                audio: false,
                video: {
                    width: this.videoWidth,
                    height: this.videoHeight,
                },
            };

            //到这一步，就解决了navigator.mediaDevices.getUserMedia 浏览器的兼容性问题

            //调用摄像头
            navigator.mediaDevices.getUserMedia(constraints)
                .then(res => {
                    console.log(res);
                    // res 是数据流（实时数据流）
                    //video 引入音视频 用的是src 而不是 数据流，这时就要借用video元素中的 srcObject
                    // console.log(this.thisVideo); 这时video的dome元素

                    //但是  srcObject 这属性 有的浏览器也没有，则要考虑兼容性问题了
                    if ('srcObject' in this.thisVideo) {
                        //如果浏览器支持srcObject
                        this.thisVideo.srcObject = res;
                    } else {
                        //否则利用 window.URL.createObjectURL(res) 将实时数据流转换成 video地址
                        this.thisVideo.src = window.URL.createObjectURL(res)
                    }

                    //视频播放  onloadedmetadata 视频数据加载完毕后就会触发
                    this.thisVideo.onloadedmetadata = function () {
                        //在这里 this指向video
                        this.play();
                    }
                })
                .catch((err) => {
                    console.log(err);
                    this.$message({
                        message: "没有开启摄像头或者浏览器不支持请求更换浏览器",
                        type: "warning",
                    });
                });
        },
        //点击拍照
        photograph() {
            // 拍照实际上就是将video当中播放的某个瞬间 用画图的方式 画到canvas当中
            //根据图片画到画布上 要用到  画笔.drawImage(图片标签，画布x起点，画布y起点，要画的宽，要画的高)

            //获取画布
            this.thisCanvas = document.querySelector(".canvasCamera");
            //获取画笔
            this.thisContext = this.thisCanvas.getContext("2d");
            //画布画图
            this.thisContext.drawImage(
                this.thisVideo,
                0,
                0,
                160,
                200
            );

            //拿到图片的信息，拿到路径
            //this.imgSrc 是base64字符串传递给学生信息录入组件
            // toDataURL返回值是包含图片信息的URL(base64)  
            //画布.toDataURL(图类型，图质量)  图纸量取值 0~1  不写，默认是 0.92
            this.imgSrc = this.thisCanvas.toDataURL("image/png",0.01);
        },
        //关闭摄像头
        closeCamera() {
            //当摄像头存在，才能关闭摄像头，才要关闭摄像头
            if (this.thisVideo && this.thisVideo !== null) {
                this.thisVideo.srcObject.getTracks()[0].stop();
                this.flag = true;//更改flag状态，让打开摄像头 按钮显示
            }
        },
        //点击重置
        resetForm() {
            //这里要考虑 有可能用户会先误碰重置  如果先碰重置时， 画布和画笔的初始值都是null，调用属性会报错
            //获取画布
            this.thisCanvas = document.querySelector(".canvasCamera");
            //获取画笔
            this.thisContext = this.thisCanvas.getContext("2d");
            //使用橡皮擦，清空画布
            this.thisContext.clearRect(0,0,this.videoWidth,this.videoHeight)
        },
        //点击提交
        submitGostudentInfo() {
            //实现图片信息传值；

            // console.log(this.imgSrc)
            //跳转到 学生信息录入
            this.$router.push({
                name: 'enter_student_info',
                query:{
                    src:this.imgSrc
                }
            })
        }
    },
    mounted() {
        this.openCamera();
    },
}
</script>

<style lang="scss" scoped>
div {
    height: 50px;
}
</style>